function Watcher(vm, exp, updater) {
    this.vm = vm;
    this.exp = exp;
    this.updater = updater;
    this.depIds = {};
    this.value = this.getVMValue();
}

Watcher.prototype = {
    update: function () {
        var value = this.getVMValue();
        var oldVal = this.value;
        if (value != oldVal) {
            this.value = value;
            this.updater.call(this.vm, value, oldVal);
        }
    },
    addDep: function (dep) {
        if (!this.depIds.hasOwnProperty(dep.id)) {
            dep.addSub(this);
            this.depIds[dep.id] = dep;
        }
    },
    getVMValue: function () {
        Dep.target = this;
        var val = this.vm.$data;
        this.exp.split(".").forEach(function (key) {
            val = val[key];
        });
        Dep.target = null;
        return val;
    }
};